package com.fy.fyspace.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.fy.fyspace.common.manager.CosManager;
import com.fy.fyspace.common.result.Result;
import com.fy.fyspace.common.utils.ImageUtil;
import com.fy.fyspace.constant.KeysConstant;
import com.fy.fyspace.constant.ResultMessageConstant;
import com.fy.fyspace.ex.BaseException;
import com.fy.fyspace.ex.ConditionException;
import com.fy.fyspace.ex.handler.ExceptionHandler;
import com.fy.fyspace.mapper.PictureMapper;
import com.fy.fyspace.mapper.SpaceMapper;
import com.fy.fyspace.mapper.UserMapper;
import com.fy.fyspace.model.dto.picture.PictureUploadDTO;
import com.fy.fyspace.model.entity.Picture;
import com.fy.fyspace.model.entity.Space;
import com.fy.fyspace.model.entity.User;
import com.fy.fyspace.model.enums.picture.PictureEditStatusEnum;
import com.fy.fyspace.model.enums.picture.PictureReviewStatusEnum;
import com.fy.fyspace.model.vo.picture.ImageMessage;
import com.fy.fyspace.model.vo.user.UserSessionVO;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.COSObjectInputStream;
import com.qcloud.cos.utils.IOUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import static org.springframework.beans.BeanUtils.copyProperties;

@Api(tags = "基础功能模块")
@Slf4j
@Component
public class BaseController {

    @Resource
    private CosManager cosManager;

    @Resource
    private PictureMapper pictureMapper;

    @Resource
    private SpaceMapper spaceMapper;

    @Resource
    private UserMapper userMapper;


    private static final Logger logger = LoggerFactory.getLogger(BaseController.class);

    /**
     * 用户查看或下载远程文件
     *
     * @param response
     * @param filePath
     */
    protected void readFile(HttpServletResponse response, String filePath) {
        OutputStream out = null;
        InputStream in = null;
        try {
            URL url = new URL(filePath);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            int responseCode = connection.getResponseCode();
            if (responseCode != HttpURLConnection.HTTP_OK) {
                return; // 或者抛出异常
            }
            in = connection.getInputStream();


            byte[] byteData = new byte[1024];
            out = response.getOutputStream();
            int len = 0;
            while ((len = in.read(byteData)) != -1) {
                out.write(byteData, 0, len);
            }
            out.flush();
        } catch (Exception e) {
            logger.error("读取文件异常", e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    logger.error("IO异常", e);
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("IO异常", e);
                }
            }
        }
    }

    /**
     * 下载文件
     *
     * @param filepath
     * @param response
     * @throws IOException
     */
    public void downloadFile(String filepath, HttpServletResponse response) throws IOException {
        // 从COS下载文件
        COSObjectInputStream cosObjectInput = null;
        try {
            // 下载文件
            COSObject cosObject = cosManager.getObject(filepath);
            cosObjectInput = cosObject.getObjectContent();
            byte[] bytes = IOUtils.toByteArray(cosObjectInput);
            // 设置响应头
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + filepath);
            // 写入响应
            response.getOutputStream().write(bytes);
            response.getOutputStream().flush();
        } catch (Exception e) {
            log.error("file download error, filepath = " + filepath, e);
            ExceptionHandler.throwIf(true, ResultMessageConstant.OPERATION_ERROR);
        } finally {
            // 释放流
            if (cosObjectInput != null) {
                cosObjectInput.close();
            }
        }
    }

    /**
     * 上传图片
     *
     * @param pictureUploadDTO
     * @param httpSession
     */
    @Transactional(rollbackFor = BaseException.class)
    public Result uploadPicture(PictureUploadDTO pictureUploadDTO, HttpSession httpSession) {
        // 1. 获取用户信息
        UserSessionVO userSessionVO = (UserSessionVO) httpSession.getAttribute(KeysConstant.LOGIN_SESSION_KEY);
        ExceptionHandler.throwIf(userSessionVO == null, ResultMessageConstant.NOT_LOGIN);

        // 2. 校验参数
        ExceptionHandler.throwIf(pictureUploadDTO == null, ResultMessageConstant.PARAMS_ERROR);
        MultipartFile file = pictureUploadDTO.getFile();
        ImageUtil.validate(file);

        // 3. 获取原始文件名
        String originalFilename = file.getOriginalFilename();
        log.info("开始处理图片上传, 文件名: {}, 大小: {}KB", originalFilename, file.getSize() / 1024);

        try {
            // 4. 获取用户空间信息
            Space space = spaceMapper.selectById(userSessionVO.getId());
            ExceptionHandler.throwIf(space == null || space.getIsDelete() == 1, ResultMessageConstant.SPACE_NOT_FOUND);

            // 5. 校验空间容量
            ExceptionHandler.throwIf(space.getTotalSize() + file.getSize() > space.getMaxSize()
                    || space.getTotalCount() + 1 > space.getMaxCount(),
                    ResultMessageConstant.INSUFFICIENT_SPACE);

            // 6. 设置图片信息
            Picture picture = new Picture();
            ImageMessage imageMessage = ImageUtil.getImageMessage(file);
            copyProperties(imageMessage, picture);

            String fileName = StrUtil.isBlank(pictureUploadDTO.getFileName()) ? originalFilename
                    : pictureUploadDTO.getFileName();
            picture.setName(fileName);
            picture.setIntroduction(pictureUploadDTO.getDescription());
            picture.setCategory(pictureUploadDTO.getCategory());
            picture.setTagsList(pictureUploadDTO.getTags());
            picture.setUserId(userSessionVO.getId());
            picture.setSpaceId(space.getId());
            picture.setFileSize(file.getSize());
            picture.setIsDelete(0);
            picture.setReviewStatus(PictureReviewStatusEnum.REVIEWING.getValue());
            picture.setIsEdit(PictureEditStatusEnum.SUBMITTED.getStatus());

            // 7. 生成文件路径
            String suffix = FileUtil.getSuffix(originalFilename);
            String filePath = String.format("/%s/picture/%s_%s_%s%s%s",
                    pictureUploadDTO.getIsPublic() == 1 ? "public" : "private",
                    userSessionVO.getId(),
                    fileName,
                    System.currentTimeMillis(),
                    ".",
                    suffix);

            // 8. 上传文件到COS
            File tempFile = null;
            try {
                tempFile = File.createTempFile(filePath, null);
                file.transferTo(tempFile);
                cosManager.putObject(filePath, tempFile);
                picture.setUrl(filePath);

                // 9. 保存图片信息到数据库
                pictureMapper.insert(picture);
                log.info("图片上传成功: {}", filePath);

                return Result.success();
            } finally {
                if (tempFile != null && tempFile.exists()) {
                    boolean delete = tempFile.delete();
                    if (!delete) {
                        log.warn("临时文件删除失败: {}", tempFile.getPath());
                    }
                }
            }
        } catch (Exception e) {
            log.error("图片上传失败, 文件名: {}, 错误: {}", originalFilename, e.getMessage());
            throw new ConditionException(ResultMessageConstant.OPERATION_ERROR);
        }
    }

    /**
     * 上传用户头像
     *
     * @param multipartFile
     * @param httpSession
     * @return
     */
    @ApiOperation(value = "上传用户头像", notes = "上传并更新用户的头像图片，保存在指定目录")
    @Transactional(rollbackFor = BaseException.class)
    public Result uploadAvatar(
            @ApiParam(value = "头像文件", required = true) MultipartFile multipartFile,
            HttpSession httpSession) {
        UserSessionVO userSessionVO = (UserSessionVO) httpSession.getAttribute(KeysConstant.LOGIN_SESSION_KEY);
        ExceptionHandler.throwIf(userSessionVO == null, ResultMessageConstant.NOT_LOGIN);

        ImageUtil.validate(multipartFile);
        String originalFilename = multipartFile.getOriginalFilename();
        log.info("开始处理头像上传, 文件名: {}, 大小: {}KB", originalFilename, multipartFile.getSize() / 1024);

        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String random = UUID.randomUUID().toString().replace("-", "").substring(0, 5);
        String baseFilePath = String.format("/user/avatar/%s", userSessionVO.getUserAccount() + random);
        String filePath = baseFilePath + suffix;

        File tempFile = null;
        try {
            // 删除旧头像
            User currentUser = userMapper.selectById(userSessionVO.getId());
            if (currentUser != null && currentUser.getUserAvatar() != null) {
                try {
                    cosManager.deleteObject(currentUser.getUserAvatar());
                    log.info("已删除旧头像: {}", currentUser.getUserAvatar());
                } catch (Exception e) {
                    log.warn("删除旧头像失败: {}", currentUser.getUserAvatar());
                }
            }

            // 上传新头像
            tempFile = File.createTempFile(filePath, null);
            multipartFile.transferTo(tempFile);
            cosManager.putObject(filePath, tempFile);

            // 更新用户信息
            User user = new User();
            user.setId(userSessionVO.getId());
            user.setUserAvatar(filePath);
            userMapper.updateById(user);

            log.info("头像上传成功: {}", filePath);
            return Result.success(filePath);

        } catch (Exception e) {
            log.error("头像上传失败, 文件名: {}, 错误: {}", originalFilename, e.getMessage());
            throw new ConditionException(ResultMessageConstant.OPERATION_ERROR);
        } finally {
            if (tempFile != null && tempFile.exists()) {
                boolean delete = tempFile.delete();
                if (!delete) {
                    log.warn("临时文件删除失败: {}", tempFile.getPath());
                }
            }
        }
    }
}
